import matplotlib.pyplot as plt
from sklearn.metrics import classification_report, confusion_matrix
import seaborn as sns
import numpy as np

class ResultTest():
    def __init__(self, history, model, X_test, Y_test):
        self.history = history
        self.model = model
        self.X_test = X_test
        self.Y_test = Y_test
        
    def eva_on_test(self) -> None:
        test_loss, test_accuracy = self.model.evaluate(self.X_test, self.Y_test)
        print(f"Test Accuracy = {test_accuracy:.2f}")
        print(f"Test Loss = {test_loss:.2f}\n")
        test_predictions = self.model.predict(self.X_test)
        test_predicted_labels = np.argmax(test_predictions, axis=1)
        true_labels = np.argmax(self.Y_test, axis=1)
        report = classification_report(true_labels, test_predicted_labels)
        print("Classification Report:\n", report)
        cm = confusion_matrix(true_labels, test_predicted_labels)
        plt.figure(figsize=(8, 6))
        sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
        plt.xlabel('Predicted Labels')
        plt.ylabel('True Labels')
        plt.title('Confusion Matrix (Test Set)')
        plt.show()
        
    
    def mon_on_training(self) -> None:
        fig, axs = plt.subplots(2, 1, figsize=(8, 8))
        axs[0].plot(self.history.history['accuracy'], label='Train Accuracy')
        axs[0].plot(self.history.history['val_accuracy'], label='Validation Accuracy')
        axs[0].set_title('Model Accuracy')
        axs[0].set_ylabel('Accuracy')
        axs[0].set_xlabel('Epoch')
        axs[0].legend()

        axs[1].plot(self.history.history['loss'], label='Train Loss')
        axs[1].plot(self.history.history['val_loss'], label='Validation Loss')
        axs[1].set_title('Model Loss')
        axs[1].set_ylabel('Loss')
        axs[1].set_xlabel('Epoch')
        axs[1].legend()
        plt.tight_layout()
        plt.show()
        
def resultTest(history, model, X_test, Y_test):
    resultTest = ResultTest(history, model, X_test, Y_test)
    print("Monitoring on model training process!\n")
    resultTest.mon_on_training()
    print("Evaluating model result!\n")
    resultTest.eva_on_test()